package com.caishi.lkx.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.zzw.common.Wrappers;
import com.zzw.common.entity.IBaseMapper;
import com.zzw.common.exception.BizRuntimeException;
import com.zzw.common.schedule.KSchedule;
import com.zzw.common.schedule.KScheduleDelay;
import com.zzw.common.utils.KZEngine;
import com.caishi.lkx.order.config.AssetsRouter;
import com.caishi.lkx.order.ienum.status.AssetsStatus;
import com.caishi.lkx.order.ienum.type.AssetsType;
import com.caishi.lkx.order.mapper.UserAssetsDataMapper;
import com.caishi.lkx.order.model.OrderModel;
import com.caishi.lkx.order.model.UserAssetsDataModel;
import com.caishi.lkx.order.service.IOrderService;
import com.caishi.lkx.order.service.IUserAssetsDataService;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * @author by keray
 * date:2021/7/15 2:15 下午
 */
@Service("userAssetsDataService")
@Slf4j
//@DubboService(interfaceClass = IUserAssetsDataBaseService.class)
public class UserAssetsDataServiceImpl implements IUserAssetsDataService {

    @Resource
    private UserAssetsDataMapper userAssetsDataMapper;

    @Resource
    private IOrderService orderService;

    @Override
    public IBaseMapper<UserAssetsDataModel, Long> getMapper() {
        return userAssetsDataMapper;
    }

    @Override
    public UserAssetsDataModel issueAssets(UserAssetsDataModel entity, OrderModel orderModel, boolean fictitious) {
        if (StrUtil.isBlank(entity.getUserId())) {
            log.error("用户资产录入时缺少用户id:data={}", entity);
            throw new BizRuntimeException("用户资产录入缺少指定用户");
        }
        if (entity.getAssetType() == null || StrUtil.isBlank(entity.getAssetMappingId())) {
            log.error("用户资产录入时无法定位资源:data={}", entity);
            throw new BizRuntimeException("用户资产录入缺少资产资源");
        }
        if (entity.getStatus() == null) {
            entity.setStatus(AssetsStatus.effective);
        }
        if (entity.getStatus() == null || entity.getEndTime() == null) {
            log.warn("用户资产录入缺少时间限制:data={}", entity);
        }
        log.info("开始录入用户资产:assert={}", entity);
        entity = AssetsRouter.router.router(entity.getAssetType()).assetsIssuePreHandler(orderModel, entity);
        if (entity != null) {
            entity.setLastOrderId(orderModel.getId());
            if (entity.getId() != null) {
                entity.getOrderIds().add(orderModel.getId());
                update(entity);
            } else {
                entity.setOrderIds(Collections.singletonList(orderModel.getId()));
                insert(entity);
            }
            // 如果用户资产是有期限的 对用户资产进行过期
            if (!fictitious && entity.getEndTime() != null) {
                // 提交过期任务
                owner(UserAssetsDataServiceImpl.class).userAssetsAutoOverdue(entity.getId(), KZEngine.generateKz(LocalDateTime.now(), entity.getEndTime().minusSeconds(-5)));
            }
            AssetsRouter.router.router(entity.getAssetType()).assetsIssuePostHandler(orderModel, entity);
        }
        return entity;
    }

    @Override
    public boolean userHaveAsset(String userId, AssetsType userAssetsType, String entityId) {
        if (StrUtil.isBlank(userId) || userAssetsType == null || StrUtil.isBlank(entityId)) {
            return false;
        }
        return userAssetsDataMapper.selectCount(Wrappers.lambdaQuery(new UserAssetsDataModel())
                .eq(UserAssetsDataModel::getUserId, userId)
                .eq(UserAssetsDataModel::getAssetType, userAssetsType)
                .eq(UserAssetsDataModel::getAssetMappingId, entityId)
                .eq(UserAssetsDataModel::getStatus, AssetsStatus.effective)
        ) > 0;
    }

    @Override
    public List<UserAssetsDataModel> userAsset(String userId, AssetsType userAssetsType, String entityId, AssetsStatus assetsStatus) {
        return userAssetsDataMapper.selectList(
                Wrappers.<UserAssetsDataModel>lambdaQuery()
                        .eq(UserAssetsDataModel::getUserId, userId)
                        .eq(UserAssetsDataModel::getAssetType, userAssetsType)
                        .eq(UserAssetsDataModel::getAssetMappingId, entityId)
                        .eq(assetsStatus != null, UserAssetsDataModel::getStatus, assetsStatus)
        );
    }

    @Override
    public List<UserAssetsDataModel> userAsset(String userId, AssetsType userAssetsType) {
        return userAsset(userId, userAssetsType, AssetsStatus.effective);
    }

    @Override
    public List<UserAssetsDataModel> userAsset(String userId, AssetsType userAssetsType, AssetsStatus assetsStatus) {
        return userAssetsDataMapper.selectList(
                Wrappers.<UserAssetsDataModel>lambdaQuery()
                        .eq(UserAssetsDataModel::getUserId, userId)
                        .eq(UserAssetsDataModel::getAssetType, userAssetsType)
                        .eq(assetsStatus != null, UserAssetsDataModel::getStatus, assetsStatus)
        );
    }

    @Override
    public boolean assetsInvalid(AssetsType assetsType, String assetId, String userId) {
        return userAssetsDataMapper.update(null, Wrappers.lambdaUpdate(new UserAssetsDataModel())
                .set(UserAssetsDataModel::getStatus, AssetsStatus.invalid)
                .eq(UserAssetsDataModel::getUserId, userId)
                .eq(UserAssetsDataModel::getAssetType, assetsType)
                .eq(UserAssetsDataModel::getAssetMappingId, assetId)
                .eq(UserAssetsDataModel::getStatus, AssetsStatus.effective)
        ) == 1;
    }

    @Override
    public boolean assetsRefund(UserAssetsDataModel assetsModel) {
        if (assetsModel == null) {
            return false;
        }
        AssetsRouter.router.router(assetsModel.getAssetType()).assetsRefundCall(null, assetsModel);
        // 提交过期任务
        if (assetsModel.getEndTime() != null) {
            owner(UserAssetsDataServiceImpl.class).userAssetsAutoOverdue(assetsModel.getId(), KZEngine.generateKz(LocalDateTime.now(), assetsModel.getEndTime()));
        }
        return this.update(assetsModel) != null;
    }


    /**
     * <p>
     * <h3>作者 keray</h3>
     * <h3>时间： 2019/9/10 16:36</h3>
     * 对用户号资产进行过期处理
     * </p>
     *
     * @param userAssetId
     * @param kz          kz延迟表达式
     * @return <p> {@link } </p>
     * @throws
     */
    @KSchedule(beanName = "userAssetsDataService", desc = "用户资产自动到期处理", dynamicDelay = true, maxRetry = 3)
    @Transactional(rollbackFor = Exception.class)
    public Boolean userAssetsAutoOverdue(Long userAssetId, @KScheduleDelay String kz) {
        log.info("处理用户过期资产 userAssetsId={}", userAssetId);
        LocalDateTime now = LocalDateTime.now();
        UserAssetsDataModel userAssetsModel = getById(userAssetId);
        if (userAssetsModel.getEndTime() == null) {
            return true;
        }
        if (userAssetsModel.getEndTime().isAfter(now)) {
            log.warn("资产未到过期时间 endTime={},now={}", userAssetsModel.getEndTime(), now);
            return false;
        }
        if (userAssetsModel.getStatus() == AssetsStatus.overdue) {
            log.warn("用户资产已经过期，无需重复执行 . userAssetsId={},modifyTime={},now={}", userAssetId,
                    userAssetsModel.getModifyTime(), now);
            return true;
        }
        OrderModel lastOrderModel = orderService.getById(userAssetsModel.getLastOrderId());
        // 资产过期前处理
        if (AssetsRouter.router.router(userAssetsModel.getAssetType()).overduePreHandler(lastOrderModel, userAssetsModel)) {
            if (userAssetsDataMapper.update(UserAssetsDataModel.builder()
                    .status(AssetsStatus.overdue)
                    .build(), Wrappers.lambdaUpdate(new UserAssetsDataModel())
                    .eq(UserAssetsDataModel::getId, userAssetId)
                    .eq(UserAssetsDataModel::getStatus, AssetsStatus.effective)
            ) == 1) {
                log.info("用户资产过期成功 userAssetId={}", userAssetId);
                // 调用资产对应的过期后处理
                AssetsRouter.router.router(userAssetsModel.getAssetType()).overduePostHandler(lastOrderModel, userAssetsModel);
                return true;
            }
            log.warn("用户资产过期状态修改失败 userAssetsId={},now={}", userAssetId, now);
        } else {
            log.warn("用户资产过期前处理拒绝 userAssetsId={},now={}", userAssetId, now);
        }
        return true;
    }

    @Override
    public List<UserAssetsDataModel> ownerGroupAssets(List<String> ownerIds) {
        if (CollUtil.isEmpty(ownerIds)) return new LinkedList<>();
        return selectList(wrappers().in(UserAssetsDataModel::getUserId, ownerIds).eq(UserAssetsDataModel::getStatus, AssetsStatus.effective));
    }

//    @Override
//    public Long addUserAssetsData(String orderId, RpcUserAssetsDataModel userAssetsDataModel) {
//        UserAssetsDataModel userAssetsDataModel1 = BeanUtil.copyProperties(userAssetsDataModel, UserAssetsDataModel.class);
//        OrderModel orderModel = new OrderModel();
//        orderModel.setId(orderId);
//        UserAssetsDataModel userAssetsDataModel2 = this.issueAssets(userAssetsDataModel1, orderModel, false);
//        return userAssetsDataModel2.getId();
//    }
//
//    @Override
//    public void delUserAssetsData(String orderId, String userId, List<Integer> assetMappingId) {
//        userAssetsDataMapper.update(null, Wrappers.<UserAssetsDataModel>lambdaUpdate()
//                .eq(UserAssetsDataModel::getAssetType, AssetsType.category)
//                .eq(UserAssetsDataModel::getUserId, userId)
//                .in(UserAssetsDataModel::getAssetMappingId, assetMappingId)
//                .eq(UserAssetsDataModel::getLastOrderId, orderId)
//                .set(UserAssetsDataModel::getStatus, AssetsStatus.invalid));
//    }
}
